﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ZT.Core.Dto;
using ZT.Core.Enums;
using ZT.Core.IService;
using ZT.Core.Model;
using ZT.Core.ORM;
using ZT.Core.Service.EventBus;
using ZT.Core.Utility;

namespace ZT.Core.Service
{
    public class FlowService : ServiceBase, IFlow
    {
        private IUnitOfWork work = null;
        private IRepository<Flow_Log> rpsFlowLog = null;
        private IRepository<Flow_Master> rpsFlowMaster = null;
        private IRepository<Flow_Point> rpsFlowPoint = null;
        private IRepository<Flow_Task> rpsFlowTask = null;
        private IRepository<Flow_User> rpsFlowUser = null;
        public FlowService(IUnitOfWork unitwork)
        {
            work = unitwork;
            UnitOfWork = unitwork;
            rpsFlowLog = work.Repository<Flow_Log>();
            rpsFlowMaster = work.Repository<Flow_Master>();
            rpsFlowPoint = work.Repository<Flow_Point>();
            rpsFlowTask = work.Repository<Flow_Task>();
            rpsFlowUser = work.Repository<Flow_User>();
        }
        /// <summary>
        /// 新建流程主表
        /// </summary>
        /// <param name="flowMaster"></param>
        /// <returns></returns>
        public ResultModel<bool> AddFlowMaster(AddFlowMaster flowMaster)
        {
            try
            {
                var checkExists = rpsFlowMaster.Any(q =>/* q.AreaID == flowMaster.AreaID &&*/ q.BusinessType == flowMaster.BusinessType);
                if (checkExists)
                {
                    throw new Exception("业务类型已经设置了审批流程");
                }
                var master = flowMaster.MAPTO<Flow_Master>();
                rpsFlowMaster.Insert(master);
                work.Commit();
                return new ResultModel<bool>(true);
            }
            catch (Exception ex)
            {
                return new ResultModel<bool>(ex);
            }
        }
        /// <summary>
        /// 撤销审批
        /// </summary>
        /// <param name="cancelParameter"></param>
        /// <returns></returns>
        public ResultModel<bool> CancelFlow(FlowCancelParameter cancelParameter)
        {
            try
            {
                var tasks = rpsFlowTask.Queryable(p => p.BusinessId == cancelParameter.BusinessId);
                if (tasks == null || !tasks.Any())
                {
                    throw new Exception("没有此业务的审批任务");
                }
                FlowJSONModel FlowModel = JsonConvert.DeserializeObject<FlowJSONModel>(tasks.FirstOrDefault().FlowJSON);
                if (!FlowModel.Flow_Master.AllowCancel)
                {
                    throw new Exception("审批流程不允许撤消");
                }
                //写入审批日志
                Flow_Log cancelLog = new Flow_Log()
                {
                    BusinessId = cancelParameter.BusinessId,
                    BusinessType = tasks.FirstOrDefault().BusinessType,
                    FlowMemo = cancelParameter.CancelMemo,
                    FlowResult = FlowResult.Cancel,
                    FlowTime = DateTime.Now,
                    FlowVersion = tasks.FirstOrDefault().FlowVersion,
                    MasterId = tasks.FirstOrDefault().MasterId,
                    PointId = tasks.FirstOrDefault().PointId,
                    UserId = AppUser.UserInfo.Id,
                    StartUserId = tasks.FirstOrDefault().StartUserId
                };
                rpsFlowLog.Insert(cancelLog);
                rpsFlowTask.Delete(q => q.BusinessId == cancelParameter.BusinessId);
                work.Commit();
                //完成审批，触发审批结束事件
                FlowComplete(new FlowCompleteEvent()
                {
                    FlowResult = FlowResult.Cancel,
                    BusinessID = cancelParameter.BusinessId,
                    BusinessType = cancelLog.BusinessType,
                    FlowMemo = cancelParameter.CancelMemo,
                    UserID = AppUser.UserInfo.Id
                });

                return new ResultModel<bool>(true);

            }
            catch (Exception ex)
            {
                return new ResultModel<bool>(ex);
            }
        }
        /// <summary>
        /// 删除流程主表
        /// </summary>
        /// <param name="flowMaster"></param>
        /// <returns></returns>
        public ResultModel<bool> DelFlowMaster(Guid flowMasterId)
        {
            try
            {
                var checkPoint = rpsFlowPoint.Any(q => q.MasterId == flowMasterId);
                if (checkPoint)
                {
                    throw new Exception("流程存在审批节点，请先删除节点");
                }
                var mastercheck = rpsFlowMaster.GetModel(flowMasterId);
                if (mastercheck == null)
                {
                    throw new Exception("审批流程不存在");
                }
                rpsFlowMaster.Delete(mastercheck);
                work.Commit();
                return new ResultModel<bool>(true);
            }
            catch (Exception ex)
            {
                return new ResultModel<bool>(ex);
            }
        }
        /// <summary>
        /// 修改流程主表
        /// </summary>
        /// <param name="flowMaster"></param>
        /// <returns></returns>
        public ResultModel<bool> EditFlowMaster(EditFlowMaster flowMaster)
        {
            try
            {
                var dbmaster = rpsFlowMaster.GetModel(flowMaster.ID);
                if (dbmaster == null)
                {
                    throw new Exception("审批流程不存在");
                }
                dbmaster = flowMaster.CopyTo(dbmaster);
                rpsFlowMaster.Update(dbmaster);
                work.Commit();
                return new ResultModel<bool>(true);
            }
            catch (Exception ex)
            {
                return new ResultModel<bool>(ex);
            }
        }
        /// <summary>
        /// 审批
        /// </summary>
        /// <param name="executeParameter"></param>
        /// <returns></returns>
        public ResultModel<bool> FlowExecute(FlowExecuteParameter executeParameter)
        {
            try
            {
                //任务
                var task = rpsFlowTask.GetModel(executeParameter.TaskId);
                if (task == null)
                {
                    throw new Exception("任务不存在");
                }
                if (AppUser.UserInfo.Id != task.UserId)
                {
                    throw new Exception("当前用户与审批用户非同一人");
                }
                FlowJSONModel FlowModel = JsonConvert.DeserializeObject<FlowJSONModel>(task.FlowJSON);

                Flow_Point ThisPoint = FlowModel.Flow_Point.FirstOrDefault(q => q.Id == task.PointId);//当前节点

                Flow_User ThisUser = FlowModel.Flow_User.Where(q => q.PointId == ThisPoint.Id && q.UserId == task.UserId).FirstOrDefault();//当前用户

                if (FlowModel.Flow_Point.FirstOrDefault(q => q.Id == task.PointId).MustFlowMemo && string.IsNullOrEmpty(executeParameter.FlowMemo))
                {
                    throw new Exception("必须填写审批意见");
                }
                //写审批日志
                Flow_Log flog = new Flow_Log
                {
                    BusinessId = task.BusinessId,
                    UserId = task.UserId,
                    MasterId = task.MasterId,
                    PointId = task.PointId,
                    StartUserId = task.StartUserId,
                    FlowVersion = task.FlowVersion,
                    FlowTime = DateTime.Now,
                    BusinessType = task.BusinessType,
                    FlowMemo = executeParameter.FlowMemo,
                    FlowResult = executeParameter.FlowResult
                };
                if (executeParameter.FlowResult == FlowResult.Deny) //如果拒绝，则删除此节点所有任务，并写日志，同时触发审批完成事件
                {

                    rpsFlowLog.Insert(flog);
                    rpsFlowTask.Delete(q => q.BusinessId == task.BusinessId);
                    work.Commit();

                    //触发审批完成事件
                    FlowComplete(new FlowCompleteEvent()
                    {
                        BusinessID = task.BusinessId,
                        BusinessType = task.BusinessType,
                        FlowMemo = executeParameter.FlowMemo,
                        FlowResult = executeParameter.FlowResult,
                        UserID = AppUser.UserInfo.Id
                    });

                    return new ResultModel<bool>(true);
                }
                else
                {
                    //同意
                    Flow_Point NextPoint = null; //取下一个 节点
                    List<Flow_User> NextUser = new List<Flow_User>(); //取下一个人员

                    switch (ThisPoint.PointType)
                    {
                        case FlowPointType.Single: //单人审批直接取下一个节点
                                                   //下一节点
                            NextPoint = FlowModel.Flow_Point.Where(q => q.MasterId == task.MasterId && q.PointIndex > ThisPoint.PointIndex).OrderBy(
                               s => s.PointIndex).FirstOrDefault();
                            //下一用户
                            if (NextPoint != null) //存在下一节点找下一用户
                            {
                                var nuser = FlowModel.Flow_User.Where(q => q.PointId == NextPoint.Id).OrderBy(s => s.UserIndex).FirstOrDefault();
                                NextUser.Add(nuser);
                            }

                            break;
                        case FlowPointType.OrderMulti: //多人顺序
                                                       //如果本节点还存在有人则 NextPoint 为ThisPoint
                            var pointcheck = FlowModel.Flow_User.Where(q => q.PointId == ThisPoint.Id && q.UserIndex > ThisUser.UserIndex).OrderBy(s => s.UserIndex).Any();

                            if (pointcheck) //本节点还有人
                            {
                                NextPoint = ThisPoint;
                                var nuser = FlowModel.Flow_User.Where(q => q.UserIndex > ThisUser.UserIndex).OrderBy(s => s.UserIndex).FirstOrDefault();
                                NextUser.Add(nuser);
                            }
                            else
                            {//本节点没有人了，则取下一个节点
                                NextPoint = FlowModel.Flow_Point.Where(q => q.MasterId == ThisPoint.MasterId && q.PointIndex > ThisPoint.PointIndex).OrderBy(s => s.PointIndex).FirstOrDefault();
                                if (NextPoint != null) // 如果有下一个节点，则找用户。
                                {
                                    var nuser = FlowModel.Flow_User.Where(q => q.PointId == NextPoint.Id).OrderBy(s => s.UserIndex).FirstOrDefault();
                                    NextUser.Add(nuser);

                                }
                            }
                            break;
                        case FlowPointType.MustMulti://多人并行
                                                     //首先看本节点是不是所有人都已经处理了
                            var usercheck = rpsFlowTask.Any(q => q.BusinessId == task.BusinessId);
                            if (!usercheck) //如果本节点还有其它用户则不处理
                            {
                                NextPoint = FlowModel.Flow_Point.Where(q => q.MasterId == ThisPoint.MasterId && q.PointIndex > ThisPoint.PointIndex).OrderBy(s => s.PointIndex).FirstOrDefault();
                                if (NextPoint != null)
                                {
                                    NextUser = FlowModel.Flow_User.Where(q => q.PointId == NextPoint.Id).ToList();
                                }
                            }
                            break;
                    }
                    //写入一个任务或完成审批
                    var newtasks = new List<Flow_Task>();

                    if (NextPoint != null && NextUser.Count() > 0)
                    {
                        foreach (var nu in NextUser)
                        {
                            newtasks.Add(new Flow_Task()
                            {
                                BusinessId = task.BusinessId,
                                BusinessType = task.BusinessType,
                                FlowJSON = task.FlowJSON,
                                FlowVersion = task.FlowVersion,
                                MasterId = task.MasterId,
                                PointId = NextPoint.Id,
                                StartTime = task.StartTime,
                                StartUserId= task.StartUserId,
                                UserId = nu.UserId
                            });
                        }
                    }

                    if (newtasks.Count() > 0) //审批未完成
                    {
                        rpsFlowLog.Insert(flog);
                        rpsFlowTask.Delete(task); //删除当前任务
                        rpsFlowTask.Insert(newtasks); //新增任务
                        work.Commit();
                    }
                    else
                    {   //审批已完成
                        rpsFlowLog.Insert(flog);
                        rpsFlowTask.Delete(task);
                        work.Commit();

                        //发起审批完成事件
                        FlowComplete(new FlowCompleteEvent()
                        {
                            UserID = AppUser.UserInfo.Id,
                            BusinessID = task.BusinessId,
                            BusinessType = task.BusinessType,
                            FlowMemo = executeParameter.FlowMemo,
                            FlowResult = executeParameter.FlowResult
                        });
                    }
                }
                return new ResultModel<bool>(true);
            }
            catch (Exception ex)
            {
                return new ResultModel<bool>(ex);
            }
        }

        public ResultModel<IEnumerable<EnumItem>> GetBusinessType()
        {
            try
            {
                var list=Command.GetItems(typeof(FlowBusinessType));
                return new ResultModel<IEnumerable<EnumItem>>(list);
            }
            catch (Exception ex)
            {
                return new ResultModel<IEnumerable<EnumItem>>(ex);
            }
        }

        /// <summary>
        /// 获取审批日志
        /// </summary>
        /// <param name="businessId"></param>
        /// <returns></returns>
        public ResultModel<IEnumerable<FlowLogView>> GetFlowLogs(Guid businessId)
        {
            try
            {
                var logs = rpsFlowLog.Queryable(q => q.BusinessId == businessId);
                var points = rpsFlowPoint.Queryable();
                var users = work.Repository<Auth_User>().Queryable();
                var profiles = work.Repository<Auth_UserProfile>().Queryable();
                var re = from log in logs
                         group log by log.FlowVersion into gversion
                         select new FlowLogView
                         {
                             FlowVersion = gversion.Key,
                             Points = from lg in gversion
                                      orderby lg.FlowTime
                                      let point = points.FirstOrDefault(q => q.Id == lg.PointId)
                                      let profile = profiles.FirstOrDefault(q => q.UserId == lg.UserId)
                                      select new FlowLogDetail
                                      {
                                          PointName = point.PointName,
                                          FlowMemo = lg.FlowMemo,
                                          FlowResult = lg.FlowResult,
                                          FlowTime = lg.FlowTime,
                                          UserCaption = profile.RelName
                                      }
                         };
                return new ResultModel<IEnumerable<FlowLogView>>(re);
            }
            catch (Exception ex)
            {
                return new ResultModel<IEnumerable<FlowLogView>>(ex);
            }
        }
        /// <summary>
        /// 获取流程主表模型
        /// </summary>
        /// <param name="flowMasterID"></param>
        /// <returns></returns>
        public ResultModel<FlowMasterModel> GetFlowMasterModel(Guid flowMasterID)
        {
            try
            {
                var master = rpsFlowMaster.GetModel(flowMasterID);
                if (master == null)
                {
                    throw new Exception("审批流程不存在");
                }
                var re = master.MAPTO<FlowMasterModel>();
                return new ResultModel<FlowMasterModel>(re);
            }
            catch (Exception ex)
            {
                return new ResultModel<FlowMasterModel>(ex);
            }
        }
        /// <summary>
        /// 分页获取流程主表信息
        /// </summary>
        /// <param name="query"></param>
        /// <returns></returns>
        public ResultModel<Pager<FlowMasterPage>> GetFlowMasterPages(PagerQuery<FlowQuery> query)
        {
            try
            {
                var masters = rpsFlowMaster.Queryable();/*q => q.AreaID == AppUser.UserInfo.AreaID || AppUser.UserInfo.AreaID == null*/
                //var rpsArea = _work.Repository<Area>();
                //var areas = rpsArea.AsQueryable();
                // var types = GetBusinessType().ToList();
                if (!string.IsNullOrEmpty(query.Query.KeyWord))
                    masters = masters.Where(o => o.FlowName.Contains(query.Query.KeyWord));

                var retemp = from m in masters
                                 // let area = areas.FirstOrDefault(q => q.Id == m.AreaID)
                                 //let btype = (BusinessType)m.BusinessType
                             select new FlowMasterPage
                             {
                                 ID = m.Id,
                                 FlowName = m.FlowName,
                                 FlowMemo = m.FlowMemo,
                                 AllowCancel = m.AllowCancel,
                                 BusinessType = m.BusinessType
                             };

                var re = new Pager<FlowMasterPage>().GetCurrentPage(retemp, query.PageSize, query.PageIndex);

                return new ResultModel<Pager<FlowMasterPage>>(re);
            }
            catch (Exception ex)
            {
                return new ResultModel<Pager<FlowMasterPage>>(ex);
            }
        }

        public ResultModel<FlowMasterPointView> GetFlowMasterPoints(Guid flowMasterId)
        {
            try
            {
                var master = rpsFlowMaster.GetModel(flowMasterId);
                if (master == null)
                {
                    throw new Exception("审批流程不存在");
                }

                var points = rpsFlowPoint.Queryable(q => q.MasterId == flowMasterId).OrderBy(s => s.PointIndex);
                var fusers = rpsFlowUser.Queryable(q => q.MasterId == flowMasterId);
                //var ausers = _work.Repository<Auth_User>().AsQueryable();
                var users = work.Repository<Auth_User>().Queryable();
                var profiles = work.Repository<Auth_UserProfile>().Queryable();
                var repoints = from p in points
                               let pusers = fusers.Where(q => q.PointId == p.Id).OrderBy(s => s.UserIndex)
                               select new FlowPointDetail
                               {
                                   PointIndex = p.PointIndex,
                                   MustFlowMemo = p.MustFlowMemo,
                                   PointName = p.PointName,
                                   PointType = p.PointType,
                                   PointUsers =from user in pusers
                                               let pro=profiles.FirstOrDefault(p=>p.UserId==user.UserId)
                                               select new PointUser
                                               {
                                                   UserId=user.UserId,
                                                   UserIndex=user.UserIndex,
                                                   UserName=pro.RelName
                                               }
                               };
                var re = new FlowMasterPointView
                {
                    MasterID = master.Id,
                    BusinessType = master.BusinessType,
                    FlowName = master.FlowName,
                    PointDetails = repoints
                };

                return new ResultModel<FlowMasterPointView>(re);

            }
            catch (Exception ex)
            {

                return new ResultModel<FlowMasterPointView>(ex);
            }
        }

        public ResultModel<Pager<FlowTaskHisPage>> GetFlowMyPartakePage(PagerQuery<FlowQuery> query)
        {
            try
            {
                var logs = rpsFlowLog.Queryable(q => q.UserId == AppUser.UserInfo.Id && (q.BusinessType == query.Query.BussinessType || query.Query.BussinessType == 0));

                var masters = rpsFlowMaster.Queryable();
                var points = rpsFlowPoint.Queryable();
                var users = work.Repository<Auth_User>().Queryable();

                var relogs = from log in logs
                             group log by log.BusinessId into bgroup
                             let master = masters.FirstOrDefault(q => q.Id == bgroup.FirstOrDefault().MasterId)
                             let point = points.FirstOrDefault(q => q.Id == bgroup.FirstOrDefault().PointId)
                             let user = users.FirstOrDefault(q => q.Id == bgroup.FirstOrDefault().StartUserId)
                             let lg = bgroup.FirstOrDefault()
                             select new FlowTaskHisPage
                             {
                                 BusinessId = lg.BusinessId,
                                 BusinessType = lg.BusinessType,
                                 FlowName = master.FlowName,
                                 StartFlowUser = user.Login,
                                 IsComplete = true
                             };

                var re = new Pager<FlowTaskHisPage>().GetCurrentPage(relogs, query.PageSize, query.PageIndex);
                return new ResultModel<Pager<FlowTaskHisPage>>(re);
            }
            catch (Exception ex)
            {

                return new ResultModel<Pager<FlowTaskHisPage>>(ex);
            }
        }

        public ResultModel<Pager<FlowTaskHisPage>> GetFlowMyStartPage(PagerQuery<FlowQuery> query)
        {
            try
            {
                var tasks = rpsFlowTask.Queryable(q => q.StartUserId == AppUser.UserInfo.Id && (q.BusinessType == query.Query.BussinessType || query.Query.BussinessType == 0));
                var taskbid = tasks.Select(s => s.BusinessId);
                var logs = rpsFlowLog.Queryable(q => q.StartUserId == AppUser.UserInfo.Id && (q.BusinessType == query.Query.BussinessType || query.Query.BussinessType == 0)
               && !taskbid.Contains(q.BusinessId)
                );

                var masters = rpsFlowMaster.Queryable();
                var points = rpsFlowPoint.Queryable();
                var users = work.Repository<Auth_User>().Queryable();


                var retasks = from task in tasks
                              let master = masters.FirstOrDefault(q => q.Id == task.MasterId)
                              let point = points.FirstOrDefault(q => q.Id == task.PointId)
                              let user = users.FirstOrDefault(q => q.Id == task.StartUserId)
                              orderby task.StartTime ascending
                              select new FlowTaskHisPage
                              {
                                  BusinessId = task.BusinessId,
                                  BusinessType = task.BusinessType,
                                  FlowName = master.FlowName,
                                  StartFlowUser = user.Login,
                                  IsComplete = false
                              };

                var relogs = from log in logs
                             group log by log.BusinessId into bgroup
                             let master = masters.FirstOrDefault(q => q.Id == bgroup.FirstOrDefault().MasterId)
                             let point = points.FirstOrDefault(q => q.Id == bgroup.FirstOrDefault().PointId)
                             let user = users.FirstOrDefault(q => q.Id == bgroup.FirstOrDefault().StartUserId)
                             let lg = bgroup.FirstOrDefault()
                             orderby lg.FlowTime
                             select new FlowTaskHisPage
                             {
                                 BusinessId = lg.BusinessId,
                                 BusinessType = lg.BusinessType,
                                 FlowName = master.FlowName,
                                 StartFlowUser = user.Login,
                                 IsComplete = true
                             };
                var data = retasks.Union(relogs);

                var re = new Pager<FlowTaskHisPage>().GetCurrentPage(data, query.PageSize, query.PageIndex);
                return new ResultModel<Pager<FlowTaskHisPage>>(re);
            }
            catch (Exception ex)
            {

                return new ResultModel<Pager<FlowTaskHisPage>>(ex);
            }
        }

        public ResultModel<Pager<FlowMyTaskPage>> GetFlowMyTaskPage(PagerQuery<FlowQuery> query)
        {
            try
            {
                var tasks = rpsFlowTask.Queryable(q => q.UserId == AppUser.UserInfo.Id && (q.BusinessType ==query.Query.BussinessType || query.Query.BussinessType == 0));
                var masters = rpsFlowMaster.Queryable();
                var points = rpsFlowPoint.Queryable();
                var users = work.Repository<Auth_User>().Queryable();
                var profile = work.Repository<Auth_UserProfile>().Queryable();

                var retemp = from task in tasks
                             let master = masters.FirstOrDefault(q => q.Id == task.MasterId)
                             let point = points.FirstOrDefault(q => q.Id == task.PointId)
                             let prof = profile.FirstOrDefault(q => q.UserId == task.StartUserId)
                             select new FlowMyTaskPage
                             {
                                 BusinessId=task.BusinessId,
                                 BusinessType= task.BusinessType,
                                 FlowName=master.FlowName,
                                 IsComplete=false,
                                 StartFlowUser=prof.RelName,
                                 TaskId=task.Id
                             };
                var re = new Pager<FlowMyTaskPage>().GetCurrentPage(retemp, query.PageSize, query.PageIndex);
                return new ResultModel<Pager<FlowMyTaskPage>>(re);
            }
            catch (Exception ex)
            {

                return new ResultModel<Pager<FlowMyTaskPage>>(ex);
            }
        }

        public ResultModel<bool> SaveFlowPoint(FlowPointParameter flowPoint)
        {
            try
            {
                List<Flow_Point> newPoints = new List<Flow_Point>();
                List<Flow_User> newFlowUsers = new List<Flow_User>();

                var flowpointsgroup = from f in flowPoint.MasterPoints
                                      group f by f.PointIndex into fg
                                      select fg;
                if (flowpointsgroup.Count() != flowPoint.MasterPoints.Count())
                {
                    throw new Exception("审批节点顺序有误");
                }

                foreach (var fp in flowPoint.MasterPoints)
                {
                    if (fp.FlowUsers == null || !fp.FlowUsers.Any())
                    {
                        throw new Exception("节点至少包含一名用户");
                    }
                    if (!Enum.IsDefined(typeof(FlowPointType), fp.PointType))
                    {
                        throw new Exception("节点类型有误");
                    }
                    var dbpoint = fp.MAPTO<Flow_Point>();
                    dbpoint.MasterId = flowPoint.MasterId;
                    dbpoint.Id = Guid.NewGuid();
                    newPoints.Add(dbpoint);
                    foreach (var fu in fp.FlowUsers)
                    {
                        var dbflowuser = fu.MAPTO<Flow_User>();
                        dbflowuser.MasterId = flowPoint.MasterId;
                        dbflowuser.PointId = dbpoint.Id;
                        newFlowUsers.Add(dbflowuser);
                    }
                }
                //删除之前数据
                rpsFlowPoint.Delete(q => q.MasterId == flowPoint.MasterId);
                rpsFlowUser.Delete(q => q.MasterId == flowPoint.MasterId);
                //保存新数据
                rpsFlowPoint.Insert(newPoints);
                rpsFlowUser.Insert(newFlowUsers);
                work.Commit();
                return new ResultModel<bool>(true);
            }
            catch (Exception ex)
            {
                return new ResultModel<bool>(ex);
            }
        }

        /// <summary>
        /// 发起审批流程
        /// </summary>
        /// <param name="startParameter"></param>
        /// <returns></returns>
        public ResultModel<bool> StartFlow(FlowStartParameter startParameter)
        {
            try
            {
                var check = Enum.IsDefined(typeof(FlowBusinessType), startParameter.BusinessType);
                if (!check)
                {
                    throw new Exception("业务类型有误");
                }
                if (startParameter.BusinessId == null || startParameter.BusinessId == Guid.Empty)
                {
                    throw new Exception("业务ID有误");
                }
                var flowcheck = rpsFlowTask.Any(q => q.BusinessId == startParameter.BusinessId);
                if (flowcheck)
                {
                    throw new Exception("业务已经发起了审批");
                }
                //不存在审批流程，直接通过审批并结束审批 发布完成事件
                var master = rpsFlowMaster.GetModel(q => q.BusinessType == startParameter.BusinessType);
                if (master == null)
                {

                    FlowComplete(new FlowCompleteEvent
                    {
                        BusinessID = startParameter.BusinessId,
                        BusinessType = startParameter.BusinessType,
                        FlowMemo = "未设置审批流程，直接通过审批。",
                        FlowResult = FlowResult.Pass,
                        UserID = AppUser.UserInfo.Id
                    });

                    return new ResultModel<bool>(true);
                }
                else
                {
                    var points = rpsFlowPoint.Queryable(q => q.MasterId == master.Id);
                    if (points == null || !points.Any())
                    {
                        //如果不存在节点，直接通过审批并结速审批，触发完成事件
                        FlowComplete(new FlowCompleteEvent
                        {
                            UserID = AppUser.UserInfo.Id,
                            BusinessID = startParameter.BusinessId,
                            BusinessType = startParameter.BusinessType,
                            FlowMemo = "未设置审批流程，直接通过审批。",
                            FlowResult = FlowResult.Pass
                        });
                        return new ResultModel<bool>(true);
                    }
                    var point = points.OrderBy(s => s.PointIndex).FirstOrDefault(); //第一个审批节点
                    if (!Enum.IsDefined(typeof(FlowPointType), point.PointType))
                    {
                        throw new Exception("节点类型有误");
                    }
                    //写入任务表
                    List<Flow_Task> tasks = new List<Flow_Task>();
                    long flowversion = (DateTime.Now.Ticks - 621355968000000000);

                    string flowJson = GetFlowJSON(master.Id);

                    switch (point.PointType)
                    {
                        case FlowPointType.Single://单人
                                                  //人员
                            Flow_User sUser = rpsFlowUser.Queryable(q => q.PointId == point.Id).OrderBy(s => s.UserIndex).FirstOrDefault();

                            tasks.Add(new Flow_Task
                            {
                                BusinessId = startParameter.BusinessId,
                                BusinessType = startParameter.BusinessType,
                                FlowVersion = flowversion,
                                MasterId = master.Id,
                                PointId = point.Id,
                                UserId = sUser.UserId,
                                FlowJSON = flowJson,
                                StartTime = DateTime.Now,
                                StartUserId = AppUser.UserInfo.Id
                            });

                            break;
                        case FlowPointType.OrderMulti: //多人顺序
                                                       //人员
                            Flow_User oUser = rpsFlowUser.Queryable(q => q.PointId == point.Id).OrderBy(s => s.UserIndex).FirstOrDefault();
                            tasks.Add(new Flow_Task()
                            {
                                BusinessId = startParameter.BusinessId,
                                BusinessType = startParameter.BusinessType,
                                FlowVersion = flowversion,
                                MasterId = master.Id,
                                PointId = point.Id,
                                UserId = oUser.UserId,
                                FlowJSON = flowJson,
                                StartTime = DateTime.Now,
                                StartUserId = AppUser.UserInfo.Id
                            });

                            break;
                        case FlowPointType.MustMulti://多人并行
                                                     //人员
                            var mUsers = rpsFlowUser.Queryable(q => q.PointId == point.Id);
                            foreach (var mu in mUsers)
                            {
                                tasks.Add(new Flow_Task()
                                {
                                    BusinessId = startParameter.BusinessId,
                                    BusinessType = startParameter.BusinessType,
                                    FlowVersion = flowversion,
                                    MasterId = master.Id,
                                    PointId = point.Id,
                                    UserId = mu.UserId,
                                    FlowJSON = flowJson,
                                    StartTime = DateTime.Now,
                                    StartUserId = AppUser.UserInfo.Id
                                });
                            }
                            break;
                    }
                    rpsFlowTask.Insert(tasks);
                    work.Commit();
                    FlowComplete(new FlowCompleteEvent
                    {
                        BusinessID = startParameter.BusinessId,
                        BusinessType = startParameter.BusinessType,
                        FlowMemo = "发起审批",
                        FlowResult = FlowResult.Started,
                        UserID = AppUser.UserInfo.Id
                    });
                    return new ResultModel<bool>(true);
                }
            }
            catch (Exception ex)
            {
                return new ResultModel<bool>(ex);
            }
        }

        /// <summary>
        /// 审批完成，发布消息总线
        /// </summary>
        /// <param name="evt"></param>
        private void FlowComplete(FlowCompleteEvent evt)
        {
            EventBus.EventBus.Instance.Publish(evt, FlowCallBack);
        }

        /// <summary>
        /// 获取审批JSON
        /// </summary>
        /// <param name="masterID"></param>
        /// <returns></returns>
        private string GetFlowJSON(Guid masterId)
        {
            var master = rpsFlowMaster.GetModel(masterId);
            var points = rpsFlowPoint.Queryable(q => q.MasterId == masterId);
            var users = rpsFlowUser.Queryable(q => q.MasterId == masterId);

            FlowJSONModel json = new FlowJSONModel
            {
                Flow_Master = master,
                Flow_Point = points,
                Flow_User = users
            };
            return Newtonsoft.Json.JsonConvert.SerializeObject(json);
        }
    }
}
